package org.jvm.nativemethod.methods.java.security;

import org.jvm.instruction.base.InstructionUtil;
import org.jvm.nativemethod.NativeMethodRegister;
import org.jvm.rtda.Object;
import org.jvm.rtda.heap.classmember.Method;
import org.jvm.rtda.thread.Frame;

/**
 * @author 海燕
 * @date 2023/2/19
 */
public class AccessControllerNativeMethod extends NativeMethodRegister {

    public static void init() throws NoSuchMethodException {
        register("java/security/AccessController", "doPrivileged", "(Ljava/security/PrivilegedAction;)Ljava/lang/Object;", AccessControllerNativeMethod.class.getDeclaredMethod("doPrivileged", Frame.class));
        register("java/security/AccessController", "doPrivileged", "(Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;;", AccessControllerNativeMethod.class.getDeclaredMethod("doPrivileged", Frame.class));
        register("java/security/AccessController", "doPrivileged", "(Ljava/security/PrivilegedExceptionAction;)Ljava/lang/Object;", AccessControllerNativeMethod.class.getDeclaredMethod("doPrivileged", Frame.class));
        register("java/security/AccessController", "doPrivileged", "(Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;", AccessControllerNativeMethod.class.getDeclaredMethod("doPrivileged", Frame.class));
        register("java/security/AccessController", "getStackAccessControlContext", "()Ljava/security/AccessControlContext;", AccessControllerNativeMethod.class.getDeclaredMethod("getStackAccessControlContext", Frame.class));
    }

    public static void doPrivileged(Frame frame) {
        Object action = frame.getLocalVars().getRef(0);

        frame.getOperandStack().pushRef(action);

        Method method = action.getKlass().getInstanceMethod("run", "()Ljava/lang/Object;");
        InstructionUtil.invokeMethod(frame, method);
    }

    public static void getStackAccessControlContext(Frame frame) {
        frame.getOperandStack().pushRef(null);
    }

}
